package com.mmx.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mmx.constant.ApproveConstant;
import com.mmx.constant.NodeConstant;
import com.mmx.domain.bean.NextNodeData;
import com.mmx.domain.bean.NodeData;
import com.mmx.domain.entity.FlowDefinition;
import com.mmx.domain.entity.FlowHistory;
import com.mmx.domain.entity.FlowInstance;
import com.mmx.domain.entity.FlowTask;
import com.mmx.extension.AbstractApprover;
import com.mmx.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @desc: 运行服务实现类
 * @author: liushuai
 * @date: 2023/1/21 14:46
 */
@Service
public class RuntimeServiceImpl implements RuntimeService {
    @Resource
    private DefinitionService flowDefinitionService;

    @Resource
    private FlowDataService flowDataService;

    @Resource
    private InstanceService instanceService;
    @Resource
    private AbstractApprover approverService;

    @Resource
    private TaskService taskService;
    @Resource
    private FlowHistoryService flowHistoryService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public FlowInstance startFlowByDefinitionKey(String definitionKey, String businessId, Map<String, Object> variables, String instanceName, String ext1, String ext2, String ext3, String createUser, String comment) {
        FlowDefinition flowDefinition = flowDefinitionService.selectFlowDefinitionByDefinitionKey(definitionKey);
        String flowData = flowDefinition.getFlowData();
        FlowInstance instance = instanceService.insertInstance(FlowInstance.builder()
                .definitionId(flowDefinition.getDefinitionId())
                .definitionKey(definitionKey)
                .instanceName(instanceName)
                .ext1(ext1)
                .ext2(ext2)
                .ext3(ext3)
                .businessId(businessId)
                .createUser(createUser)
                .build());

        NextNodeData nextNodeData = flowDataService.taskFlow(flowData, null, variables);
        flowHistoryService.insertFlowHistory(FlowHistory.builder()
                .approveType(ApproveConstant.APPROVE_TYPE_START)
                .assignee(createUser)
                .createTime(new Date())
                .nodeId(nextNodeData.getStartNodeId())
                .comment(StrUtil.isEmpty(comment) ? "发起流程审批" : comment)
                .nodeName("开始节点")
                .nodeType(NodeConstant.START)
                .build());
        List<FlowTask> tasks = new ArrayList<>();
        for (NodeData nodeData : nextNodeData.getNodeDataList()) {
            String branchId = StrUtil.uuid();
            //判断只要是用户节点,则返回下一个节点审批人
            if (NodeConstant.USER_TASK.equals(nodeData.getType())) {
                List<String> approver = approverService.getApprover(nodeData, variables);
                for (String assignee : approver) {
                    tasks.add(FlowTask.builder()
                            .branchId(branchId)
                            .businessId(businessId)
                            .instanceId(instance.getInstanceId())
                            .assignee(assignee)
                            .nodeId(nodeData.getId())
                            .nodeName(nodeData.getProperties().getNodeName())
                            .instanceName(instance.getInstanceName())
                            .build());
                }
            }
        }
        taskService.insertTaskBatch(tasks);
        return instance;
    }

    @Override
    public void complete(Long taskId, Map<String, Object> variables, Integer approveType) {
        if(ObjectUtil.isNull(taskId)){
            throw new RuntimeException("任务ID不能为空");
        }
        //流程任务
        FlowTask flowTask = taskService.selectTaskByTaskId(taskId);
        //根据流程实例Id获取流程定义
        FlowDefinition flowDefinition =  flowDefinitionService.selectFlowDefinitionByInstanceId(flowTask.getInstanceId());

    }

}
